package com.sfdk.core
{
import com.sfdk.log.Logger;

import flash.display.Graphics;
import flash.display.Sprite;
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.events.KeyboardEvent;
import flash.external.ExternalInterface;
import flash.ui.Keyboard;
    import flash.utils.Dictionary;

    public class KeyboardListener extends EventDispatcher
	{
		private var _keyPressed : Array;
        private var _keyCodePressed : Array;
		private var _gameProxy : GameProxy;

        public static var instance : KeyboardListener;
		private var _namedEventMap : Dictionary;

		public function KeyboardListener(gameProxy : GameProxy)
		{
			if(instance == null)
				instance = this;
			else
			{
				Logger.error("KeyboardListener :: KeyboardListener cannot be instantiated twice");
				return;
			}
            init(gameProxy);
        }

        private function init(gameProxy : GameProxy) : void
        {
			_keyPressed = new Array();
            _keyCodePressed = new Array();
			_gameProxy = gameProxy;

            _gameProxy.stage.addEventListener(KeyboardEvent.KEY_DOWN, dispatchKeyDown);
			_gameProxy.stage.addEventListener(KeyboardEvent.KEY_UP, dispatchKeyUp);
			//registerExternalInterface();

            _namedEventMap = new Dictionary();
            _namedEventMap[Keyboard.SPACE] =  "SPACE";
            _namedEventMap[Keyboard.ENTER] =  "ENTER";
            _namedEventMap[Keyboard.LEFT] =  "LEFT";
            _namedEventMap[Keyboard.RIGHT] =  "RIGHT";
            _namedEventMap[Keyboard.UP] =  "UP";
            _namedEventMap[Keyboard.DOWN] =  "DOWN";
		}
		
		private function dispatchKeyDown(e : KeyboardEvent) : void
		{
			if(e.ctrlKey)
				ExternalInterface.call("ReturnFocusToJS");
			else
 				processKeyDown(e.charCode, e.ctrlKey, e.altKey, e.shiftKey, e.keyCode);
		}
		
		private function processKeyDown(charCode : uint, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean, keyCode : uint = 0) : void
		{
            var strCode : String = String.fromCharCode(charCode);
			if(_keyPressed.indexOf(strCode) == -1)
				_keyPressed.push(strCode);
            if(_keyCodePressed.indexOf(keyCode) == -1)
                _keyCodePressed.push(keyCode);
			// On dispatch les touches spéciales à part
            if(_namedEventMap[keyCode] != null)
            {
                dispatchEvent(new Event(_namedEventMap[keyCode]));
            }
            else
			{
				var outCode : String="";
				if(ctrlKey)
					outCode+="CTRL+";
				if(altKey)
					outCode+="ALT+";
				if(shiftKey)
					outCode+="SHIFT+";
				if(strCode != "'")
					outCode+=strCode.toUpperCase();
				else
					outCode+=strCode;
				
				//Logger.debug("KeyDown "+outCode);
				dispatchEvent(new Event(outCode));
				dispatchEvent(new Event("Keyboard-"+keyCode));
			}
		}
		
		private function dispatchKeyUp(e : KeyboardEvent) : void
		{ 
			var strCode : String = String.fromCharCode(e.charCode);
			var index : int = _keyPressed.indexOf(strCode);
			if(index != -1)
				_keyPressed.splice(index,1);
            index = _keyCodePressed.indexOf(e.keyCode);
            if(index != -1)
                _keyCodePressed.splice(index, 1);
			//Logger.debug("KeyUp "+strCode);
            if(_namedEventMap[e.keyCode] != null)
            {
                dispatchEvent(new Event(_namedEventMap[e.keyCode]+"-UP"));
            }
			dispatchEvent(e);
            dispatchEvent(new Event("Keyboard-"+e.keyCode+"-UP"));
		}
		
		public function isPressed(charCode : uint) : Boolean
		{
			var strCode : String = String.fromCharCode(charCode);
			var index : int = _keyPressed.indexOf(strCode);
			return index != -1;
		}

        public function isKeyCodePressed(keyCode : uint) : Boolean
		{
			var index : int = _keyCodePressed.indexOf(keyCode);
			return index != -1;
		}
		
		private function registerExternalInterface() : void
		{
			ExternalInterface.addCallback("onKeyPressIE", onIEKeyPress);
			ExternalInterface.addCallback("onKeyDownIE", onIEKeyDown);
			ExternalInterface.addCallback("onKeyUpIE", onIEKeyUp);
			ExternalInterface.addCallback("openRightClick", onRightClick);
			
			ExternalInterface.addCallback("onKeyPressMZ", onMZKeyPress);
			ExternalInterface.addCallback("onKeyDownMZ", onMZKeyDown);
			ExternalInterface.addCallback("onKeyUpMZ", onMZKeyUp);
		}
		
		private function onRightClick() : void
		{
			var mx:int = _gameProxy.stage.mouseX;
			var my:int = _gameProxy.stage.mouseY;
			var canvas : Sprite = new Sprite();
			if(my > 0 && my < _gameProxy.stage.stageHeight && mx > 0 && mx < _gameProxy.stage.stageWidth) {
				var g : Graphics = canvas.graphics;
				g.beginFill(0x000000, 1);
                g.drawCircle(mx,my,10);
				g.endFill();
			}
			_gameProxy.addChild(canvas);
		}
		
		private function onIEKeyPress(keyCode : uint, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean) : void
		{
			processKeyDown(keyCode, ctrlKey, altKey, shiftKey); 
		}
		
		private function onIEKeyDown(keyCode : uint, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean) : void
		{
			processKeyDown(keyCode, ctrlKey, altKey, shiftKey); 
		}
		
		private function onIEKeyUp(keyCode : uint, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean) : void
		{
			var strCode : String = String.fromCharCode(keyCode);
			var index : int = _keyPressed.indexOf(strCode);
			if(index != -1)
				_keyPressed.splice(index,1);
			//Logger.debug("KeyUp "+strCode.toUpperCase());
		}
		
		private function onMZKeyPress(charCode : String,keyCode : String, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean) : void
		{
			//trace("keyPress "+charCode+" "+keyCode+" "+ctrlKey+" "+altKey+" "+shiftKey);	
		}
		
		private function onMZKeyDown(keyCode : uint, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean) : void
		{
			processKeyDown(keyCode, ctrlKey, altKey, shiftKey);
		}
		
		private function onMZKeyUp(charCode : uint, keyCode : uint, ctrlKey : Boolean, altKey : Boolean, shiftKey : Boolean) : void
		{
			var strCode : String = String.fromCharCode(charCode);
			var index : int = _keyPressed.indexOf(strCode);
			if(index != -1)
				_keyPressed.splice(index,1);
			//Logger.debug("KeyUp "+strCode.toUpperCase())
		}

	}
}